4.3 返回值
有返回值的函数,必须有明确的return终止语句。
func test(x int)int{
if x>0{
return 1
}else if x<0{
return -1
}
} // 错误:missing return at end of function
除非有panic,或者无break的死循环,则无须return终止语句。
func test(x int)int{
for{
break
}
} // 错误:missing return at end of function借鉴自动态语言的多返回值模式,函数得以返回更多状态,尤其是error模式。
import"errors"
func div(x,y int) (int,error) { // 多返回值列表必须使用括号
if y==0{
return 0,errors.New("division by zero")
}
return x/y,nil
}稍有不便的是没有元组(tuple)类型,也不能用数组、切片接收,但可用“_”忽略掉不想要的返回值。多返回值可用作其他函数调用实参,或当作结果直接返回。
func div(x,y int) (int,error) {
if y==0{
return 0,errors.New("division by zero")
}
return x/y,nil
}
func log(x int,err error) {
fmt.Println(x,err)
}
func test() (int,error) {
return div(5,0) // 多返回值用作return结果
}
func main() {
log(test()) // 多返回值用作实参
}
命名返回值
对返回值命名和简短变量定义一样,优缺点共存。
func paging(sql string,index int) (count int,pages int,err error) {
}
从这个简单的示例可看出,命名返回值让函数声明更加清晰,同时也会改善帮助文档和代码编辑器提示。
命名返回值和参数一样,可当作函数局部变量使用,最后由return隐式返回。
func div(x,y int) (z int,err error) {
if y==0{
err=errors.New("division by zero")
return
}
z=x/y
return // 相当于 "return z,err"
}这些特殊的“局部变量”会被不同层级的同名变量遮蔽。好在编译器能检查到此类状况,只要改为显式return返回即可。
func add(x,y int) (z int) {
{
z:=x+y // 新定义的同名局部变量,同名遮蔽
return // 错误:z is shadowed during return(改成 "return z" 即可)
}
return
}除遮蔽外,我们还必须对全部返回值命名,否则编译器会搞不清状况。
func test() (int,s string,e error) {
return 0, "",nil // 错误:cannot use 0(type int)as type string in return argument
}显然编译器在处理return语句的时候,会跳过未命名返回值,无法准确匹配。
如果返回值类型能明确表明其含义,就尽量不要对其命名。
func NewUser() (*User,error)